package com.jerry.hm.datastructure.array;

import java.util.Arrays;
import java.util.Iterator;
import java.util.function.Consumer;
import java.util.stream.IntStream;

/**
 * 动态数组
 *
 * @author Jerry
 * @since 2024/9/29 15:55
 */
public class DynamicArray implements Iterable<Integer> {

    /**
     * 数组长度
     */
    private int size = 0;

    /**
     * 数组容量
     */
    private int capacity = 8;

    /**
     * 内部数组
     */
    private int[] array = {};

    /**
     * 数组末尾添加元素
     *
     * @param element 待添加元素
     */
    public void addLast(int element) {
        add(size, element);
    }

    /**
     * 数组指定索引添加元素
     *
     * @param index   指定索引
     * @param element 待添加元素
     */
    public void add(int index, int element) {
        if (index < 0 || index > size) {
            throw new IndexOutOfBoundsException();
        }

        // 扩容
        resize();

        System.arraycopy(array, index, array, index + 1, size - index);
        array[index] = element;
        size++;
    }

    /**
     * 修改数组容量
     */
    private void resize() {
        if (size == 0) {
            array = new int[capacity];
        }
        // 容量检查
        if (size == capacity) {
            capacity += capacity >>> 1;
            int[] newArray = new int[capacity];
            System.arraycopy(array, 0, newArray, 0, size);
            array = newArray;
        }
    }

    /**
     * 移除指定索引元素
     *
     * @param index 指定索引
     * @return 被移除的元素
     */
    public int remove(int index) {
        if (index < 0 || index > size) {
            throw new IndexOutOfBoundsException();
        }
        int target = array[index];

        if (index < size - 1) {
            System.arraycopy(array, index + 1, array, index, size - index - 1);
        }
        size--;

        return target;
    }

    /**
     * 获取指定索引的元素
     *
     * @param index 指定索引
     * @return 指定索引的元素
     */
    public int get(int index) {
        if (index < 0 || index > size) {
            throw new IndexOutOfBoundsException();
        }
        return array[index];
    }

    /**
     * 遍历并打印所有元素
     *
     * @param consumer 消费行为
     */
    public void foreach(Consumer<Integer> consumer) {
        for (int i = 0; i < size; i++) {
            consumer.accept(array[i]);
        }
    }

    @Override
    public Iterator<Integer> iterator() {

        return new Iterator<>() {

            int i = 0;

            @Override
            public boolean hasNext() {
                return i < size;
            }

            @Override
            public Integer next() {
                return array[i++];
            }
        };
    }

    public IntStream stream() {
        return IntStream.of(Arrays.copyOfRange(array, 0, size));
    }
}
